package com.fan.shop.views.bean;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;

import org.apache.log4j.Logger;

import com.fan.shop.businesslogic.PurchaseOrderCancelProcess;
import com.fan.shop.businesslogic.PurchaseOrderCompleteProcess;
import com.fan.shop.businesslogic.PurchaseOrderCreateProcess;
import com.fan.shop.businesslogic.PurchaseOrderFinaliseProcess;
import com.fan.shop.businesslogic.PurchaseOrderLineDeleteProcess;
import com.fan.shop.businesslogic.PurchaseOrderUpdateProcess;
import com.fan.shop.domain.Item;
import com.fan.shop.domain.PurchaseLine;
import com.fan.shop.domain.PurchaseOrder;
import com.fan.shop.global.ShopGlobalVariables;
import com.fan.shop.model.commonbrowser.CommonBrowser;
import com.fan.shop.model.userclass.PurchaseLineUserClass;
import com.fan.shop.services.ItemService;
import com.fan.shop.services.PurchaseLineService;
import com.fan.shop.services.PurchaseOrderService;
import com.fan.shop.services.StockService;
import com.fan.shop.services.StoreService;
import com.fan.shop.services.TransactionReferenceService;
import com.fan.shop.services.UserService;

@ManagedBean(name = "purchaseOrderBean")
@RequestScoped
public class PurchaseOrderBean extends ShopBean {

	private static Logger logger = Logger.getLogger(PurchaseOrderBean.class);

	@ManagedProperty(value = "#{itemService}")
	private ItemService itemService;

	@ManagedProperty(value = "#{userService}")
	private UserService userService;

	@ManagedProperty(value = "#{storeService}")
	private StoreService storeService;

	@ManagedProperty(value = "#{stockService}")
	private StockService stockService;

	@ManagedProperty(value = "#{purchaseOrderService}")
	private PurchaseOrderService purchaseOrderService;

	@ManagedProperty(value = "#{purchaseLineService}")
	private PurchaseLineService purchaseLineService;

	@ManagedProperty(value = "#{transactionReferenceService}")
	private TransactionReferenceService transactionReferenceService;

	private String itemCodesString;
	private String storeCodeString;

	private static List<PurchaseLineUserClass> attachedPurchaseLines = new ArrayList<PurchaseLineUserClass>();
	private static Map<String, Item> itemsMap = new HashMap<String, Item>();

	private String poNumber;
	private String storeCode;
	private String officerCode;
	private Date transactionDate;
	private BigDecimal postage;
	private String status;
	private String comments;
	private String buyer;
	private String deliveryAddress;

	private String transactionCode;

	private int mode;

	public static Logger getLogger() {
		return logger;
	}

	public static void setLogger(Logger logger) {
		PurchaseOrderBean.logger = logger;
	}

	public ItemService getItemService() {
		return itemService;
	}

	public void setItemService(ItemService itemService) {
		this.itemService = itemService;
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public StoreService getStoreService() {
		return storeService;
	}

	public void setStoreService(StoreService storeService) {
		this.storeService = storeService;
	}

	public StockService getStockService() {
		return stockService;
	}

	public void setStockService(StockService stockService) {
		this.stockService = stockService;
	}

	public PurchaseOrderService getPurchaseOrderService() {
		return purchaseOrderService;
	}

	public void setPurchaseOrderService(
			PurchaseOrderService purchaseOrderService) {
		this.purchaseOrderService = purchaseOrderService;
	}

	public PurchaseLineService getPurchaseLineService() {
		return purchaseLineService;
	}

	public void setPurchaseLineService(PurchaseLineService purchaseLineService) {
		this.purchaseLineService = purchaseLineService;
	}

	public TransactionReferenceService getTransactionReferenceService() {
		return transactionReferenceService;
	}

	public void setTransactionReferenceService(
			TransactionReferenceService transactionReferenceService) {
		this.transactionReferenceService = transactionReferenceService;
	}

	public String getItemCodesString() {
		return itemCodesString;
	}

	public void setItemCodesString(String itemCodesString) {
		this.itemCodesString = itemCodesString;
	}

	public String getStoreCodeString() {
		return storeCodeString;
	}

	public void setStoreCodeString(String storeCodeString) {
		this.storeCodeString = storeCodeString;
	}

	public List<PurchaseLineUserClass> getAttachedPurchaseLines() {
		return attachedPurchaseLines;
	}

	@SuppressWarnings("static-access")
	public void setAttachedPurchaseLines(
			List<PurchaseLineUserClass> attachedPurchaseLines) {
		this.attachedPurchaseLines = attachedPurchaseLines;
	}

	public Map<String, Item> getItemsMap() {
		return itemsMap;
	}

	@SuppressWarnings("static-access")
	public void setItemsMap(Map<String, Item> itemsMap) {
		this.itemsMap = itemsMap;
	}

	public String getPoNumber() {
		return poNumber;
	}

	public void setPoNumber(String poNumber) {
		this.poNumber = poNumber;
	}

	public String getStoreCode() {
		return storeCode;
	}

	public void setStoreCode(String storeCode) {
		this.storeCode = storeCode;
	}

	public String getOfficerCode() {
		return officerCode;
	}

	public void setOfficerCode(String officerCode) {
		this.officerCode = officerCode;
	}

	public Date getTransactionDate() {
		return transactionDate;
	}

	public void setTransactionDate(Date transactionDate) {
		this.transactionDate = transactionDate;
	}

	public BigDecimal getPostage() {
		return postage;
	}

	public void setPostage(BigDecimal postage) {
		this.postage = postage;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getComments() {
		return comments;
	}

	public void setComments(String comments) {
		this.comments = comments;
	}

	public String getBuyer() {
		return buyer;
	}

	public void setBuyer(String buyer) {
		this.buyer = buyer;
	}

	public String getDeliveryAddress() {
		return deliveryAddress;
	}

	public void setDeliveryAddress(String deliveryAddress) {
		this.deliveryAddress = deliveryAddress;
	}

	public String getTransactionCode() {
		return transactionCode;
	}

	public void setTransactionCode(String transactionCode) {
		this.transactionCode = transactionCode;
	}

	public int getMode() {
		if (poNumber != null && poNumber.trim().length() > 0) {
			mode = ShopGlobalVariables.EDIT_MODE;
		} else {
			mode = ShopGlobalVariables.NEW_MODE;
		}
		return mode;
	}

	public void setMode(int mode) {
		this.mode = mode;
	}

	public PurchaseOrderBean() {
		super();
		setReturnedValues();
	}

	public void setReturnedValues() {
		Map<String, Object> map = FacesContext.getCurrentInstance()
				.getExternalContext().getRequestMap();
		if (map.containsKey("common_browser")) {
			CommonBrowser commonBrowser = (CommonBrowser) map
					.get("common_browser");

			itemService = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getItemService();
			userService = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getUserService();
			storeService = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getStoreService();
			transactionReferenceService = ((PurchaseOrderBean) commonBrowser
					.getCaller()).getTransactionReferenceService();

			purchaseOrderService = ((PurchaseOrderBean) commonBrowser
					.getCaller()).getPurchaseOrderService();

			purchaseLineService = ((PurchaseOrderBean) commonBrowser
					.getCaller()).getPurchaseLineService();

			poNumber = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getPoNumber();
			storeCode = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getStoreCode();
			officerCode = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getOfficerCode();
			transactionDate = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getTransactionDate();
			postage = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getPostage();
			status = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getStatus();
			comments = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getComments();
			buyer = ((PurchaseOrderBean) commonBrowser.getCaller()).getBuyer();
			deliveryAddress = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getDeliveryAddress();
			transactionCode = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getTransactionCode();

			itemCodesString = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getItemCodesString();
			storeCodeString = ((PurchaseOrderBean) commonBrowser.getCaller())
					.getStoreCodeString();

			if (commonBrowser.getReturnList().size() == 0) {
				return;
			}

			if (commonBrowser.getTriggerField().equals("po_number")) {
				poNumber = commonBrowser.getReturnList().get(0);
				loadPurchaseOrderDetails();
			}
			if (commonBrowser.getTriggerField().equals("officer_code")) {
				officerCode = commonBrowser.getReturnList().get(0);
			}
			if (commonBrowser.getTriggerField().equals("store_code")) {
				storeCode = commonBrowser.getReturnList().get(0);
			}
			if (commonBrowser.getTriggerField().equals("transaction_code")) {
				transactionCode = commonBrowser.getReturnList().get(0);
			}
			if (commonBrowser.getTriggerField().equals("item_code")) {

				for (String item_code : commonBrowser.getReturnList()) {
					if (!itemsMap.containsKey(item_code)) {
						itemsMap.put(item_code, itemService.getItem(item_code));

						PurchaseLineUserClass purchaseLineUserClass = new PurchaseLineUserClass();
						purchaseLineUserClass.setItemCode(item_code);
						purchaseLineUserClass.setPrice(new BigDecimal(0.00));
						purchaseLineUserClass.setQuantity(0);

						attachedPurchaseLines.add(purchaseLineUserClass);
					}

				}

			}

		}
	}

	public String loadItemsAction() {
		itemsMap = new HashMap<String, Item>();
		attachedPurchaseLines = new ArrayList<PurchaseLineUserClass>();
		if (itemCodesString.trim().length() > 0) {
			for (String item_code : parseItemCodes(itemCodesString)) {
				itemsMap.put(item_code, itemService.getItem(item_code));

				PurchaseLineUserClass lineUserClass = new PurchaseLineUserClass();
				lineUserClass.setPoNumber("");
				lineUserClass.setItemCode(item_code);
				lineUserClass.setPrice(new BigDecimal(0.00));
				lineUserClass.setQuantity(0);

				attachedPurchaseLines.add(lineUserClass);

			}
		}

		if (storeCodeString.trim().length() > 0) {
			storeCode = storeCodeString;
		}
		return "purchase_order.faces";
	}

	public String[] parseItemCodes(String itemCodes) {
		String[] itemCodeList = itemCodes.split(";");
		return itemCodeList;
	}

	public String openPurchaseOrderAction() {
		CommonBrowser commonBrowser = new CommonBrowser();
		commonBrowser.setTriggerField("po_number");
		commonBrowser
				.setParentPage("../../views/management/purchase_order.faces");
		commonBrowser.setSelectionMode("single");
		commonBrowser.setShopService(purchaseOrderService);
		commonBrowser.setCaller(this);
		FacesContext.getCurrentInstance().getExternalContext().getRequestMap()
				.put("common_browser", commonBrowser);
		return "../../views/commonbrowser/commonbrowser.faces";

	}

	public String openStoreAction() {
		CommonBrowser commonBrowser = new CommonBrowser();
		commonBrowser.setTriggerField("store_code");
		commonBrowser
				.setParentPage("../../views/management/purchase_order.faces");
		commonBrowser.setSelectionMode("single");
		commonBrowser.setShopService(storeService);
		commonBrowser.setCaller(this);
		FacesContext.getCurrentInstance().getExternalContext().getRequestMap()
				.put("common_browser", commonBrowser);
		return "../../views/commonbrowser/commonbrowser.faces";

	}

	public String openUserAction() {
		CommonBrowser commonBrowser = new CommonBrowser();
		commonBrowser.setTriggerField("officer_code");
		commonBrowser
				.setParentPage("../../views/management/purchase_order.faces");
		commonBrowser.setSelectionMode("single");
		commonBrowser.setShopService(userService);
		commonBrowser.setCaller(this);
		FacesContext.getCurrentInstance().getExternalContext().getRequestMap()
				.put("common_browser", commonBrowser);
		return "../../views/commonbrowser/commonbrowser.faces";

	}

	public String openTransactionReferenceAction() {
		CommonBrowser commonBrowser = new CommonBrowser();
		commonBrowser.setTriggerField("transaction_code");
		commonBrowser
				.setParentPage("../../views/management/purchase_order.faces");
		commonBrowser.setSelectionMode("single");
		transactionReferenceService
				.setGroupCode(ShopGlobalVariables.PURCHASE_ORDER_GROUP);
		commonBrowser.setShopService(transactionReferenceService);
		commonBrowser.setCaller(this);
		FacesContext.getCurrentInstance().getExternalContext().getRequestMap()
				.put("common_browser", commonBrowser);
		return "../../views/commonbrowser/commonbrowser.faces";

	}

	public String openStocksAction() {

		CommonBrowser commonBrowser = new CommonBrowser();
		commonBrowser.setTriggerField("item_code");
		commonBrowser
				.setParentPage("../../views/management/purchase_order.faces");
		commonBrowser.setSelectionMode("multi");
		stockService.setStoreCode(storeCode);
		commonBrowser.setShopService(stockService);
		commonBrowser.setCaller(this);
		FacesContext.getCurrentInstance().getExternalContext().getRequestMap()
				.put("common_browser", commonBrowser);
		return "../../views/commonbrowser/commonbrowser.faces";

	}

	public String removePurchaseLineAction(String item_code) {
		if (itemsMap.containsKey(item_code)) {
			itemsMap.remove(item_code);
			int index = 0;
			for (index = 0; index < attachedPurchaseLines.size(); index++) {
				if (attachedPurchaseLines.get(index).getItemCode()
						.equals(item_code)) {
					break;
				}
			}

			if (poNumber != null && poNumber.trim().length() > 0) {
				PurchaseOrderLineDeleteProcess purchaseOrderLineDeleteProcess = new PurchaseOrderLineDeleteProcess();
				purchaseOrderLineDeleteProcess.setPoNumber(poNumber);
				purchaseOrderLineDeleteProcess
						.setItemCode(attachedPurchaseLines.get(index)
								.getItemCode());
				purchaseOrderLineDeleteProcess
						.setPurchaseLineService(purchaseLineService);
				purchaseOrderLineDeleteProcess.setPurchaseOrderService(purchaseOrderService);
				purchaseOrderLineDeleteProcess.setStockService(stockService);
				
				
				
				int result = purchaseOrderLineDeleteProcess.process();
				if (result == ShopGlobalVariables.SUCCESS) {
					attachedPurchaseLines.remove(index);
					poNumber = purchaseOrderLineDeleteProcess.getPoNumber();
					loadPurchaseOrderDetails();
				}
				else
				{
					attachedPurchaseLines.remove(index);
				}
			} else {
				attachedPurchaseLines.remove(index);
			}
		}
		return "purchase_order.faces";
	}

	public String savePurchaseOrderAction() {
		if (getMode() == ShopGlobalVariables.NEW_MODE) {
			int result = createPurchaseOrder();
			if (result == ShopGlobalVariables.SUCCESS) {
				loadPurchaseOrderDetails();
			}
		}
		else if (getMode() == ShopGlobalVariables.EDIT_MODE) {
			int result = savePurchaseOrder();
			if (result == ShopGlobalVariables.SUCCESS) {
				loadPurchaseOrderDetails();
			}
		}

		return "purchase_order.faces";
	}

	private int createPurchaseOrder() {
		PurchaseOrderCreateProcess purchaseOrderCreateProcess = new PurchaseOrderCreateProcess();
		purchaseOrderCreateProcess.setPoNumber(poNumber);
		purchaseOrderCreateProcess.setTransactionCode(transactionCode);
		purchaseOrderCreateProcess.setOfficerCode(officerCode);
		purchaseOrderCreateProcess.setStoreCode(storeCode);

		transactionDate = new Date();
		purchaseOrderCreateProcess.setTransactionDate(transactionDate);
		purchaseOrderCreateProcess.setPostage(postage);
		purchaseOrderCreateProcess.setBuyer(buyer);
		purchaseOrderCreateProcess.setStatus(status);
		purchaseOrderCreateProcess.setComments(comments);
		purchaseOrderCreateProcess.setDeliveryAddress(deliveryAddress);
		purchaseOrderCreateProcess.setAttachedPOLines(attachedPurchaseLines);
		purchaseOrderCreateProcess
				.setTransactionReferenceService(transactionReferenceService);
		purchaseOrderCreateProcess.setStoreService(storeService);
		purchaseOrderCreateProcess.setUserService(userService);
		purchaseOrderCreateProcess
				.setPurchaseOrderService(purchaseOrderService);
		purchaseOrderCreateProcess.setPurchaseLineService(purchaseLineService);
		purchaseOrderCreateProcess.setStockService(stockService);
		purchaseOrderCreateProcess.setItemService(itemService);

		int result = purchaseOrderCreateProcess.process();
		if (result == ShopGlobalVariables.FAILED) {
		} else {
			poNumber = purchaseOrderCreateProcess.getPoNumber();

		}
		return result;

	}

	private int savePurchaseOrder() {
		PurchaseOrderUpdateProcess purchaseOrderUpdateProcess = new PurchaseOrderUpdateProcess();
		purchaseOrderUpdateProcess.setPoNumber(poNumber);
		purchaseOrderUpdateProcess.setTransactionCode(transactionCode);
		purchaseOrderUpdateProcess.setOfficerCode(officerCode);
		purchaseOrderUpdateProcess.setStoreCode(storeCode);

		purchaseOrderUpdateProcess.setTransactionDate(transactionDate);
		purchaseOrderUpdateProcess.setPostage(postage);
		purchaseOrderUpdateProcess.setBuyer(buyer);
		purchaseOrderUpdateProcess.setStatus(status);
		purchaseOrderUpdateProcess.setComments(comments);
		purchaseOrderUpdateProcess.setDeliveryAddress(deliveryAddress);
		purchaseOrderUpdateProcess.setAttachedPOLines(attachedPurchaseLines);
		purchaseOrderUpdateProcess.setItemService(itemService);
		purchaseOrderUpdateProcess.setStoreService(storeService);
		purchaseOrderUpdateProcess.setUserService(userService);
		purchaseOrderUpdateProcess
				.setPurchaseOrderService(purchaseOrderService);
		purchaseOrderUpdateProcess.setPurchaseLineService(purchaseLineService);

		purchaseOrderUpdateProcess.setStockService(stockService);
		purchaseOrderUpdateProcess.setItemService(itemService);
		purchaseOrderUpdateProcess
				.setTransactionReferenceService(transactionReferenceService);

		int result = purchaseOrderUpdateProcess.process();
		if (result == ShopGlobalVariables.FAILED) {
			return result;
		} else {
			poNumber = purchaseOrderUpdateProcess.getPoNumber();

			return result;
		}
	}

	public String completePurchaseOrderAction() {
		if (getMode() == ShopGlobalVariables.EDIT_MODE) {

			int result = savePurchaseOrder();

			if (result == ShopGlobalVariables.FAILED) {
				logger.info("Failed saing purchase order");
				return "purchase_order.faces";
			}
			PurchaseOrderCompleteProcess purchaseOrderCompleteProcess = new PurchaseOrderCompleteProcess();
			purchaseOrderCompleteProcess.setPoNumber(poNumber);
			purchaseOrderCompleteProcess.setComments(comments);
			purchaseOrderCompleteProcess
					.setPurchaseOrderService(purchaseOrderService);
			purchaseOrderCompleteProcess.setStockService(stockService);

			result = purchaseOrderCompleteProcess.process();

			if (result == ShopGlobalVariables.FAILED) {
				return "purchase_order.faces";
			} else {
				poNumber = purchaseOrderCompleteProcess.getPoNumber();
				loadPurchaseOrderDetails();
				return "purchase_order.faces";
			}

		}
		return "purchase_order.faces";
	}

	public String finalisePurchaseOrderAction() {
		if (getMode() == ShopGlobalVariables.EDIT_MODE) {

			PurchaseOrderFinaliseProcess purchaseOrderFinaliseProcess = new PurchaseOrderFinaliseProcess();
			purchaseOrderFinaliseProcess.setPoNumber(poNumber);
			purchaseOrderFinaliseProcess.setComments(comments);
			purchaseOrderFinaliseProcess
					.setPurchaseOrderService(purchaseOrderService);
			int result = purchaseOrderFinaliseProcess.process();

			if (result == ShopGlobalVariables.FAILED) {
				return "purchase_order.faces";
			} else {
				poNumber = purchaseOrderFinaliseProcess.getPoNumber();
				loadPurchaseOrderDetails();
				return "purchase_order.faces";
			}
		}
		return "purchase_order.faces";
	}

	public String cancelPurchaseOrderAction() {
		if (getMode() == ShopGlobalVariables.EDIT_MODE) {

			// savePurchaseOrder();

			PurchaseOrderCancelProcess purchaseOrderCancelProcess = new PurchaseOrderCancelProcess();
			purchaseOrderCancelProcess.setPoNumber(poNumber);
			purchaseOrderCancelProcess.setComments(comments);
			purchaseOrderCancelProcess
					.setPurchaseOrderService(purchaseOrderService);
			purchaseOrderCancelProcess.setStockService(stockService);
			int result = purchaseOrderCancelProcess.process();

			if (result == ShopGlobalVariables.FAILED) {
				return "purchase_order.faces";
			} else {
				poNumber = purchaseOrderCancelProcess.getPoNumber();
				loadPurchaseOrderDetails();
				return "purchase_order.faces";
			}
		}
		return "purchase_order.faces";
	}

	private void loadPurchaseOrderDetails() {
		if (getMode() == ShopGlobalVariables.EDIT_MODE) {
			PurchaseOrder purchaseOrder = purchaseOrderService
					.getPurchaseOrder(poNumber);
			officerCode = purchaseOrder.getOfficerCode();
			storeCode = purchaseOrder.getStoreCode();
			transactionDate = purchaseOrder.getTransactionDate();
			postage = purchaseOrder.getPostage();
			status = purchaseOrder.getStatus();
			buyer = purchaseOrder.getBuyer();
			deliveryAddress = purchaseOrder.getDeliveryAddress();
			comments = purchaseOrder.getComments();
			transactionCode = purchaseOrder.getTransactionCode();

			attachedPurchaseLines = new ArrayList<PurchaseLineUserClass>();
			itemsMap = new HashMap<String, Item>();

			for (PurchaseLine purchaseLine : purchaseOrderService
					.getPurchaseLines(poNumber)) {
				attachedPurchaseLines
						.add((PurchaseLineUserClass) purchaseLineService
								.copy(purchaseLine));
				itemsMap.put(purchaseLine.getId().getItemCode(),
						itemService.getItem(purchaseLine.getId().getItemCode()));
			}
		}
	}

}
